RAG 비법노트 심화편 — 딥다이브 학습 노트

출처: 뉴런데브 — RAG 비법노트 심화편


학습 로드맵

EP1 LLM 증강질의 복습
 │  (모델 튜닝 한계 → 프롬프트 튜닝 대안)
 ▼
EP2 임베딩 불일치 보완
 │  (인코더 정체 → 쿼리-데이터 시멘틱 갭 → 하이브리드 검색)
 ▼
EP3 리랭커로 품질 끌어올리기
 │  (크로스 인코더 → LLM 기반 리랭커)
 ▼
EP4 컨텍스트 압축
 │  (어텐션 희석 → Stuff/MapReduce/MapRefine/ClusterMapRefine)
 ▼
EP5 RAG와 프롬프트
 │  (입력 편향 + 출력 편향 → 어텐션 희석 → 토큰 임베딩 차원)
 ▼
EP6 RAPTOR의 허실
 │  (계층적 클러스터링 → 차원 축소 파괴 / 컨텍스트 혼합 / 유사 시멘틱)
 ▼
EP7 RAG 시스템 평가
 │  (정확성·관련성·이행성·안정성 → LLM-as-Judge → 테스트셋 생성)
 ▼
EP8 RAG 시스템 튜닝
    (청크 튜닝 → 벡터 검색 튜닝 → 비임베딩 강화 → 부분 요소 교체)

선수 지식 체크리스트

  • [ ] 트랜스포머 아키텍처 (어텐션, 멀티헤드, FFN)
  • [ ] 인코더 vs 디코더 차이
  • [ ] 임베딩·코사인 유사도 개념
  • [ ] 벡터 DB 기본 사용법 (Chroma, FAISS 등)
  • [ ] RAG 기본 파이프라인 (→ 기본편 EP1~EP9 참고)

추천 학습 순서

  1. EP1~EP2: 기본편 복습 + 임베딩 한계 이해
  2. EP3~EP4: 검색 품질 향상 기법 (리랭커 → 컨텍스트 압축)
  3. EP5: 프롬프트 엔지니어링의 원리 (어텐션 편향)
  4. EP6: RAPTOR 비판적 분석
  5. EP7~EP8: 평가·튜닝 사이클

EP1. LLM 증강질의 복습 — 모델 튜닝 vs 프롬프트 튜닝

강의 핵심 요약

LLM 튜닝에는 모델 튜닝(파라미터 직접 수정)과 프롬프트 튜닝(입력으로 편향 유도) 두 가지만 존재한다. 모델 튜닝은 데이터 부족, 비용, 균형 파괴 문제로 실무에서 극히 어렵고, 대부분의 RAG 시스템은 프롬프트 튜닝(= 입력 편향)으로 해결한다. Agentic AI(Qwen, Anthropic MCP)는 외부 도구 연동의 새로운 패러다임이다.

딥다이브

모델 튜닝이 어려운 이유

문제 상세
데이터 요구량 7B 모델 유의미 튜닝에 150~200만 completion 필요. 기업 도메인 데이터는 보통 4만 개 수준
비용 7B 모델 학습에 GPU 5천만원+ 필요 (추론은 RTX 4080, ~200만원으로 충분)
균형 파괴 도메인 특화 학습 시 기존 상식 추론이 망가짐 (catastrophic forgetting)
학습 비용 비율 학습 비용 ≈ 추론 비용 × 10

LoRA/QLoRA 레이어별 튜닝 전략

LLM의 학습 가능 레이어는 어텐션 레이어FFN(MLP) 레이어 두 곳이다:

  • 어텐션 레이어: 건드리면 위험 → LoRA/QLoRA에서도 보통 회피
  • FFN/MLP 레이어: 비교적 안전하게 미세 조정 가능
  • 임베딩 모델: 모델 자체는 건드리지 않고, 하위에 로지스틱 회귀층이나 MLP를 추가
# LoRA 설정 예시 — FFN 레이어만 타겟
from peft import LoraConfig

lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["gate_proj", "up_proj", "down_proj"],  # FFN만
    lora_dropout=0.05,
    task_type="CAUSAL_LM"
)

⚠️ 최신 업데이트: 2025~2026 벤치마크에 따르면 QLoRA는 full fine-tuning 대비 80~90% 품질을 달성하며, LoRA는 0.1~1% 파라미터만 학습해도 거의 동등한 결과를 보인다. 단, LaRA 벤치마크(2025)는 RAG vs Fine-tuning에서 "만능 해법은 없다"고 결론 — 태스크 유형별 선택이 핵심이다.

Agentic AI

  • Qwen 3.5: 알리바바의 오픈소스 모델. 외부 도구 연동(tool calling)에 특화하여 학습
  • Anthropic Claude + MCP: 유료 모델 중 tool picking 정확도가 가장 높음
  • 핵심: 모델 자체를 튜닝하지 않고, 프롬프트 + 도구 명세로 외부 시스템과 연동

실무 적용

# RAG에서 모델 튜닝 대신 프롬프트 튜닝으로 해결하는 패턴
system_prompt = """당신은 {domain} 전문가입니다.
아래 컨텍스트만을 기반으로 답변하세요.
컨텍스트에 없는 내용은 "정보 없음"이라 답하세요.

[컨텍스트]
{retrieved_chunks}
"""
# → 모델 파라미터를 건드리지 않고 입력 편향만으로 도메인 특화

핵심 체크포인트

  • ✅ 모델 튜닝은 데이터 100만+ 필요, 비용·균형 파괴 리스크 → 실무에서 프롬프트 튜닝이 현실적
  • ✅ LoRA/QLoRA 사용 시에도 어텐션 레이어는 회피하고 FFN만 타겟
  • ✅ Agentic AI는 모델 튜닝 없이 프롬프트 + 도구 명세로 외부 연동

EP2. 임베딩 불일치 보완 — 인코더의 정체와 시멘틱 갭

강의 핵심 요약

임베딩이 불일치하는 근본 원인은 두 가지: (1) 인코더 모델 자체가 구식 어텐션 기반(BERT)으로 정체되어 있고, (2) 쿼리(의도 기반)와 데이터(팩트 기반)의 시멘틱 구조가 태생적으로 다르다. 보완 방법으로 BM25/Elasticsearch 기반 하이브리드 검색을 병행한다.

딥다이브

인코더 모델 정체의 구조적 원인

디코더 (GPT, Claude, Gemini)         인코더 (BERT 계열)
─────────────────────────          ──────────────────
• Group Attention                   • 2018년 이후 어텐션 발전 없음
• MoE (Mixture of Experts)          • 대부분 BERT가 시드 모델
• Flash Attention                   • 투자·연구 관심 없음
• 계속 진화 중                       • 사실상 버려진 아키텍처
  • 인코더: 입력 → 어텐션 1회 → 결론 (폐쇄망). 빠르지만 출력 편향 없음
  • 디코더: 입력 → 토큰 생성 반복 (어텐션 매회 재계산). 느리지만 프롬프트 통제 가능
  • 결과: 인코더 기반 임베딩 = 구식 어텐션 → 허접한 시멘틱 표현

⚠️ 최신 업데이트: 2025~2026 MTEB 리더보드 상위 모델 — Cohere embed-v4 (65.2), OpenAI text-embedding-3-large (64.6), Voyage AI voyage-3.5 시리즈. Google은 gemini-embedding-001(Matryoshka Representation Learning 적용)과 EmbeddingGemma(308M 파라미터, 온디바이스 특화)를 발표했다. 그러나 이들도 여전히 인코더 기반이며 디코더 대비 어텐션 진화 폭은 제한적이다.

쿼리-데이터 시멘틱 불일치

구분 쿼리 (사용자 질의) 데이터 (청크)
성격 의도 + 컨텍스트 + 감정 복합 팩트 중심, 단순 서술
시멘틱 복합적 의도 기반 임베딩 사실 기반 임베딩
예시 "이번 분기에 삼성전자가 괜찮은 거야?" "삼성전자 2분기 영업이익 14조원"
결과 두 임베딩의 코사인 유사도가 낮음

BM25 하이브리드 검색

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever

# 벡터 검색 + BM25 키워드 검색 앙상블
ensemble = EnsembleRetriever(
    retrievers=[vector_retriever, bm25_retriever],
    weights=[0.5, 0.5]  # 시멘틱 50% + 키워드 50%
)
  • BM25: 형태소 분석 → 토큰 인덱스 → TF-IDF 기반 토큰 카운트 비교
  • Elasticsearch/Solr 계열의 풀텍스트 인덱싱도 동일 원리
  • 임베딩이 못 잡는 키워드 매칭을 보완

실무 적용

# 정규화 후 코사인 유사도 계산 (임베딩 원리)
import numpy as np

def cosine_similarity(a, b):
    # 정규화: 각 원소 제곱 합의 루트로 나눔
    a_norm = a / np.linalg.norm(a)
    b_norm = b / np.linalg.norm(b)
    return np.dot(a_norm, b_norm)

# 임베딩 모델 출력은 비정규화 상태 → 벡터 DB 저장 전 정규화 필수

핵심 체크포인트

  • ✅ 인코더 기반 임베딩 모델은 BERT 시대에서 어텐션이 멈춰 있어 시멘틱 표현이 제한적
  • ✅ 쿼리(의도)와 데이터(팩트)는 태생적으로 시멘틱 구조가 달라 임베딩 불일치 발생
  • ✅ BM25 하이브리드 검색으로 키워드 매칭을 보완 — 저비용 고효과

EP3. RAG 품질을 끌어올리는 리랭커

강의 핵심 요약

벡터 DB 검색 결과의 유사도 점수를 신뢰할 수 없으므로, N개 결과를 리랭커로 재정렬하여 상위 X개만 LLM에 전달한다. 크로스 인코더 리랭커는 빠르지만 구식 어텐션의 한계를 공유하며, 디코더(LLM) 기반 리랭커는 프롬프트 통제·도메인 지식 주입·중복 제거가 가능하다.

딥다이브

리랭커 기본 흐름

사용자 질의 → 임베딩 → 벡터 DB 검색 (N개)
                            ↓
                     리랭커 재정렬 (N → X개)
                            ↓
              시스템 프롬프트 + X개 컨텍스트 + 질의 → LLM → 답변

크로스 인코더 리랭커

  • 학습 방법: BERT를 [CLS] query [SEP] passage 형태로 학습
  • 학습 데이터: MS MARCO Passage Ranking (크로스 인코더 90%가 이 데이터 기반)
  • 구조: 쿼리 1개 + 정답 1~2개 + 오답 다수 → 유사도 점수(0~1) 출력 학습
  • 장점: 인코더이므로 어텐션 1회 → 빠른 속도
  • 한계:
  • N개 문서에 대해 N번 개별 호출 (쿼리+문서 쌍마다 1회)
  • 프롬프트 통제 불가 — 모델 학습 성향 그대로
  • 도메인 지식 주입 불가
  • 중복 문서 판별 불가

LLM 기반 리랭커 (디코더)

항목 크로스 인코더 LLM 리랭커
호출 횟수 N번 (문서당 1회) 1번 (전체 문서 listwise)
프롬프트 통제 불가 "최신 소스 우선" 등 자연어 지시 가능
도메인 지식 학습 데이터 한정 프롬프트로 도메인 규칙 주입 가능
중복 판별 불가 전체 문서를 한 번에 보므로 가능
속도 빠름 (인코더) 느림 (디코더)
비용 저비용 고비용

⚠️ 최신 업데이트: 2025~2026 권장 아키텍처는 2-stage 하이브리드 — (1) 크로스 인코더로 top-20 축소 (5~10ms), (2) LLM listwise 리랭킹으로 top-10 최종 정렬 (200~500ms). ZeroEntropy의 zerank-1은 NDCG@10에서 +28% 향상을 보이며, LLM 정확도의 95%를 3x 빠른 속도로 달성한다.

실무 적용

# 크로스 인코더 리랭커 사용 예시
from sentence_transformers import CrossEncoder

reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")

# N개 검색 결과를 재정렬
pairs = [(query, doc.page_content) for doc in search_results]
scores = reranker.predict(pairs)

# 상위 X개만 선택
top_x = sorted(zip(scores, search_results), reverse=True)[:5]
# LLM 기반 listwise 리랭커 (프롬프트 통제 가능)
rerank_prompt = """다음 문서들을 질문과의 관련성 순으로 정렬하세요.
중복 문서는 하나만 남기세요.
최신 정보를 우선하세요.

질문: {query}
문서들: {documents}

JSON 형식으로 정렬된 문서 ID 목록을 반환하세요."""

핵심 체크포인트

  • ✅ 벡터 DB 유사도 점수는 신뢰할 수 없음 → 리랭커로 재정렬 필수
  • ✅ 크로스 인코더는 빠르지만 N번 호출·프롬프트 통제 불가 — 1차 필터용
  • ✅ LLM 리랭커는 느리지만 listwise 1회 호출·프롬프트 통제·중복 제거 가능 — 최종 정렬용

EP4. RAG 결과를 프롬프트에 '잘' 넣기 — 컨텍스트 압축

강의 핵심 요약

검색 결과를 그대로 프롬프트에 넣으면 어텐션 희석으로 답변 품질이 떨어진다. LLM에게 요약을 시키면, LLM이 편향을 가장 잘 일으킬 형태로 압축하므로 합리적이다. 요약 기법: Stuff, MapReduce, MapRefine, ClusterMapRefine.

딥다이브

왜 LLM이 요약해야 하는가

핵심 논리: 편향을 일으키는 당사자(LLM)가 편향에 최적인 형태로 요약하는 것이 가장 효율적이다.

"네가 요약한 걸 나중에 내가 주면,
 네가 그 편향을 잘 일으킬 수 있게 요약해줘"
→ LLM이 자기 자신의 어텐션 특성을 알고 있으므로 최적 요약 가능

비용 구조: 요약은 1회성 비용 → 이후 사용자 질의마다 작은 토큰만 전송

4가지 요약 기법

기법 원리 장점 단점
Stuff 전체 문서를 한 번에 LLM에 전달 → 요약 단순 큰 모델 필요, 문서 크기 제한
MapReduce 페이지별 요약 → 요약의 요약 → ... 최종 1개 대규모 문서 처리 가능 서사 구조 손실
MapRefine 1장 요약 → 1장 요약+2장 함께 요약 → ... 순차적 서사 구조 보존 순차 처리로 느림
ClusterMapRefine RAPTOR식 클러스터링 + Refine 계층적 요약 클러스터링 문제 그대로 상속

Refine의 정체

Refine은 영어 단어가 아니라 고유명사다. 이 동네(요약 기법)에서의 Refine이란: - 앞에서 요약한 결과를 이용해서 뒤의 데이터를 합쳐 다시 요약본을 만드는 것 - Chain of Density(CoD) 프롬프트가 Refine을 재귀적으로 활용

# MapRefine 패턴 구현
from langchain.chains.summarize import load_summarize_chain

# 서사 구조가 있는 문서 (1장→2장→3장 순서 중요)
chain = load_summarize_chain(
    llm,
    chain_type="refine",  # 앞 요약을 바탕으로 뒤를 요약
    refine_prompt=refine_prompt  # 편향 최적화 지시 포함
)

⚠️ 최신 업데이트: LangChain의 ContextualCompressionRetriever, LlamaIndex의 tree/refine synthesizer가 컨텍스트 압축의 표준 도구로 자리잡았다. 2025 기준 LlamaIndex는 retrieval accuracy 35% 향상을 달성했으며, LangChain은 LangGraph를 통해 복잡한 추론 워크플로우를 지원한다.

실무 적용

from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor

# LLM 기반 컨텍스트 압축 retriever
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor,
    base_retriever=vector_retriever
)
# → 검색 결과를 LLM이 질문에 관련된 부분만 추출하여 압축

핵심 체크포인트

  • ✅ 대량 컨텍스트를 그대로 넣으면 어텐션 희석 → LLM 요약으로 압축 필수
  • ✅ 서사 구조가 있는 문서는 MapRefine (순차 요약), 없으면 MapReduce (병렬 요약)
  • ✅ 요약은 1회성 비용 — 이후 질의마다 작은 토큰만 전송하여 비용 절감

EP5. RAG와 프롬프트 — 어텐션 편향의 원리

강의 핵심 요약

프롬프트는 인간이 작성할 수 없는 프로그래밍 언어다. LLM만이 "이 단어 조합이 어떤 편향을 유도할지" 예측할 수 있다. 어텐션 편향에는 입력 편향(시스템 프롬프트)과 출력 편향(LLM 자체 생성 토큰)이 있으며, 토큰 수가 늘수록 어텐션 희석이 발생한다.

딥다이브

입력 편향 vs 출력 편향

입력 편향 (Input Bias)
─────────────────────
시스템 프롬프트 + 컨텍스트로 유도
→ "이 데이터를 기반으로 답변하세요"

출력 편향 (Output Bias)
─────────────────────
LLM이 생성한 토큰이 다음 토큰 생성에 영향
→ Chain of Thought(CoT)가 대표적 활용
→ "중간 과정을 떠들면서 마지막에 답변해봐"

디코더의 원리: 100개 토큰 → 101번째 생성 → 101개 토큰 → 102번째 생성 → ... - 내가 입력한 토큰 + LLM이 생성한 토큰 모두가 다음 토큰에 영향 - 리즈닝 모델의 원리가 바로 출력 편향 활용

어텐션 희석 (Attention Dilution)

10개 토큰 중 7번 토큰의 기여도:  1/10 = 10%
20,000개 토큰 중 7번 토큰의 기여도: 1/20,000 = 0.005%
→ 토큰이 많아질수록 개별 토큰의 영향력 급감
  • 출력을 많이 시키면 초반 프롬프트가 점점 희석 → "뒤에 가면 기억도 못해"
  • 대책: 토큰 임베딩 차원을 늘린 모델 사용

⚠️ 최신 업데이트: Adobe Research NoLiMa 벤치마크(2025)에서 12개 모델 중 11개가 32K 토큰에서 baseline 대비 50% 이하 성능을 보였다. GPT-4o도 99.3% → 69.7%로 하락. 2025 arXiv 연구는 "100% 완벽한 검색이 이루어져도 입력 길이 증가 시 13.9~85% 성능 저하"를 보고했다.

토큰 임베딩 차원과 희석의 관계

차원이 작은 모델 (예: 256d)
→ 토큰 희석 시 의미 보존 어려움

차원이 큰 모델 (예: 3072d, OpenAI text-embedding-3-large)
→ 어텐션 계산 효과가 많은 차원에 분포
→ 개별 토큰 영향 감소해도 차원별로는 충분한 기여
→ 어텐션 헤드를 더 많이 만들 수 있음
→ 긴 토큰에서도 맥락 유지 가능

컨텍스트 확장 모델의 활용

  • 토큰 임베딩 차원은 작지만 입력 컨텍스트만 늘린 모델 존재
  • 용도: 인코더처럼 활용 — "대규모로 받아서 요약해줘"
  • 짧은 출력 생성 시 희석 전에 답변 완료 가능
  • 인코더 대신 디코더를 쓰는 이유: 프롬프트 통제 가능

실무 적용

# 프롬프트 설계 시 어텐션 편향 활용 원칙
# 1. 중요한 지시는 프롬프트 앞쪽에 배치 (입력 편향 극대화)
# 2. 출력 길이를 제한하여 희석 방지
# 3. CoT로 출력 편향 활용

system_prompt = """[최우선 지시: JSON 형식으로만 답변]  ← 앞쪽 배치
역할: {domain} 전문가
컨텍스트: {context}
제약: 3문장 이내로 답변하세요.  ← 출력 제한으로 희석 방지
"""

# 프롬프트 사용 빈도별 설계 전략
# - 비정기적/특수 문제 → 느슨한 프롬프트 OK
# - 매일 스케줄 실행 → 일관된 결과 필요 → 정교한 프롬프트
# - 함수적 호출 (JSON 포맷 등) → 최고 수준의 프롬프트 기술 필요

핵심 체크포인트

  • ✅ 프롬프트 = LLM만이 작성할 수 있는 프로그래밍 언어 (어텐션 편향 유도)
  • ✅ 입력 편향(시스템 프롬프트) + 출력 편향(CoT) 조합으로 원하는 답 유도
  • ✅ 어텐션 희석 대책 = 토큰 임베딩 차원이 큰 모델 + 출력 길이 제한

EP6. RAPTOR의 허실 — 계층적 클러스터링의 함정

강의 핵심 요약

RAPTOR는 청크 → 임베딩 → 차원 축소 → 클러스터링 → 요약 → 다시 임베딩의 계층 구조를 만든다. 이론적으로 추상적 질문은 상위 노드, 구체적 질문은 하위 리프에서 검색된다. 그러나 차원 축소의 시멘틱 파괴, 컨텍스트 혼합, 유사 시멘틱 문제로 실무에서 잘 작동하지 않는다.

딥다이브

RAPTOR 동작 흐름

청크들 → 임베딩 (756차원)
              ↓
         차원 축소 (5차원 또는 2차원!)   ← 여기서 시멘틱 파괴
              ↓
         GMM 클러스터링 → 그룹 형성
              ↓
         그룹 내 청크 모아서 LLM 요약
              ↓
         요약문 다시 임베딩
              ↓
         (반복) → 계층적 트리 구조 완성

3대 치명적 문제

1. 차원 축소에 의한 시멘틱 파괴

756차원 → 5차원 축소 시 시멘틱 정보 대부분 소실: - 차원이 많은 이유 = 다양한 시멘틱을 표현하기 위함 - 5차원으로 축소하면 코사인 유사도 비교 자체가 무의미

2. 컨텍스트 혼합 (Context Mixing)

시멘틱 구조가 비슷하지만 컨텍스트가 완전히 다른 청크들이 함께 클러스터링:

"임금이 죽었다" (한국 역사)  ─┐
                              ├→ 시멘틱 유사 → 같은 클러스터!
"천황이 죽었다" (일본 역사)  ─┘
→ 컨텍스트는 완전히 다르지만 문장 구조가 같아서 임베딩이 유사
→ 함께 요약하면 의미 없는 결과
  • 해결하려면 컨텍스트 격벽을 사람이 수동으로 설정해야 함 → 비현실적

3. 유사 시멘틱 문제 (Similar Semantics)

기업 데이터, 뉴스 기사 등에서 문장 구조(템플릿)는 같고 명사만 다른 경우: - 기사 기레기들의 포맷이 똑같아서 시멘틱 구조가 동일 - RDB 테이블을 문장으로 변환해도 구조 반복 - 임베딩 값이 거의 동일 → 클러스터링해도 무의미 → 요약도 무의미

⚠️ 최신 업데이트: Stanford CS224N 연구(2025)는 RAPTOR의 GMM 클러스터링 한계를 지적하며, Adaptive Graph Clustering(그래프 커뮤니티 탐지)을 대안으로 제시했다. HIRO(Hierarchical Information Retrieval Optimization)는 DFS 기반 재귀적 유사도 임계값 + 가지치기로 정보 과부하를 해결한다. PageIndex는 문서의 실제 페이지/섹션 계층 구조를 미러링하는 방식으로 RAPTOR의 임의적 클러스터링 문제를 회피한다.

실무 적용

# RAPTOR를 써도 되는 경우의 체크리스트
raptor_suitable = all([
    "문서 주제가 단일하거나 매우 유사",       # 세종대왕 문서 → OK
    "컨텍스트가 상이한 내용이 혼재하지 않음",   # 한국+일본 역사 → NG
    "유사 시멘틱 반복 데이터가 아님",          # RDB 테이블 변환 → NG
    "클러스터링 결과가 유의미한지 검증 가능",
])

# RAPTOR 대안: 단순하지만 효과적인 접근
# 1. 메타데이터 기반 필터링 (문서 카테고리별 격벽)
# 2. 하이브리드 검색 (벡터 + BM25)
# 3. 2-stage 리랭킹 (크로스 인코더 + LLM)

핵심 체크포인트

  • ✅ RAPTOR의 756차원→5차원 축소는 시멘틱을 파괴 — 클러스터링 자체가 무의미해질 수 있음
  • ✅ 컨텍스트가 다른 청크가 시멘틱 구조 유사로 함께 클러스터링되는 문제
  • ✅ RAPTOR 논문의 데이터셋은 RAPTOR에 맞게 정교하게 구성된 것 — 범용 데이터에는 주의

EP7. RAG 시스템 평가하기

강의 핵심 요약

RAG 평가의 핵심 4대 지표: 정확성, 관련성, 이행성, 안정성. 보조 지표로 컨텍스트 일관성, 논리적 일관성, 간결성, 창의성이 있다. 평가 자체도 LLM으로 수행하며(LLM-as-Judge), 테스트셋도 LLM이 생성한다.

딥다이브

4대 핵심 평가 지표

지표 설명 난이도
정확성 (Accuracy) 올바르고 정확한 답변인가 매우 어려움 — "독도는 누구 땅?" 같은 문제
관련성 (Relevance) 질문 의도에 부합하는가 상대적으로 측정 용이
이행성 (Compliance) 지시한 대로 수행하는가 양날의 검 — 이행성 높음 = 시키지 않은 건 안 함
안정성 (Safety) 위험한 답변을 하지 않는가 기밀 누출, 인명 살상 정보 등

보조 지표의 상호 관계

이행성 ←──→ 컨텍스트 일관성 (같이 흐름)
  │              │
  └──→ 논리적 일관성 (자기 모순성 방지)

이행성 높음 = 멍청함 (시킨 것만 함)
이행성 낮음 = 지멋대로 (컨텍스트 일관성도 나빠짐)

간결성 ←──→ 창의성 (상충 관계)
저파라미터 모델 → 확률 분포 뻔함 → 창의성 낮음

LLM-as-Judge 평가 방식

# LLM으로 RAG 품질 평가
evaluation_prompt = """다음 질문-답변 쌍을 평가하세요.

질문: {question}
정답(기대): {expected_answer}
실제 답변: {actual_answer}
참조 컨텍스트: {context}

평가 항목 (각 1~5점):
1. 정확성: 사실적으로 올바른가?
2. 관련성: 질문 의도에 부합하는가?
3. 이행성: 지시사항을 준수했는가?
4. 안전성: 위험한 내용이 없는가?

JSON으로 점수와 근거를 반환하세요."""

디퓨전 모델 — 토큰 생성의 대안

  • GPT 방식: 토큰을 하나씩 순차 생성
  • 디퓨전 모델: 전체 답변을 "뿌옇게 → 선명하게" 확산 역과정으로 생성
  • 잉크 비유: 물에 잉크 한 방울 → 파란물이 됨 → 이 파란물에서 원래 잉크를 역추적하는 학습

⚠️ 최신 업데이트: RAGAS 프레임워크가 RAG 평가의 사실상 표준으로 자리잡았다. 핵심 메트릭 — Context Precision(검색된 청크 중 실제 활용 비율), Context Recall(필요 정보의 검색 커버리지), Faithfulness(답변이 컨텍스트에 충실한지). RAGAS는 LangChain, LlamaIndex, Haystack 등 주요 프레임워크와 통합을 지원한다.

실무 적용

# RAGAS를 이용한 RAG 시스템 평가
from ragas import evaluate
from ragas.metrics import (
    faithfulness,
    answer_relevancy,
    context_precision,
    context_recall,
)

result = evaluate(
    dataset=eval_dataset,
    metrics=[faithfulness, answer_relevancy,
             context_precision, context_recall],
)
print(result)  # 각 메트릭별 0~1 점수
# LLM으로 테스트셋 생성
test_gen_prompt = """다음 청크들을 기반으로 QA 테스트셋을 만들어주세요.

청크들: {chunks}

각 질문에 대해:
1. 질문 (자연스러운 한국어)
2. 기대 답변
3. 관련 청크 ID 목록
4. 난이도 (easy/medium/hard)

JSON 배열로 반환하세요."""

핵심 체크포인트

  • ✅ 핵심 4대 지표: 정확성·관련성·이행성·안정성 — 거의 모든 평가에 공통
  • ✅ 이행성은 양날의 검 — 높으면 시킨 것만 하고, 낮으면 컨텍스트 일관성도 무너짐
  • ✅ 평가도 LLM, 테스트셋도 LLM이 생성 — 사람이 만들 수 없는 규모

EP8. RAG 시스템 튜닝하기

강의 핵심 요약

RAG 튜닝은 4단계 파이프라인: 청크 튜닝 → 벡터 검색 튜닝 → 비임베딩 요소 강화 → 부분 요소 교체. 가장 영향이 크지만 부담도 큰 것이 체인 변경과 임베딩 모델 변경이고, 가장 현실적인 것이 비임베딩 요소 강화(BM25 병행, 메타데이터 등)다. 청크 튜닝이 가장 기본이자 가장 많은 기업이 실패하는 지점이다.

딥다이브

RAG 튜닝 4단계

1. 청크 튜닝           ← 가장 기본, 여기서 대부분 실패
   ↓
2. 벡터 검색 튜닝       ← 임베딩 모델 교체 (비용 큼)
   ↓
3. 비임베딩 요소 강화    ← BM25 병행, 메타데이터 (현실적)
   ↓
4. 부분 요소 교체       ← 리랭커 교체 등 (국소적 변경)

청크 튜닝 — 대부분이 실패하는 이유

스플리터 선택이 핵심: 대부분 기업이 단순 글자수 기반 스플리터를 사용하여 실패

문제: "앞 문장 중간 ~ 뒷 문장 앞부분"으로 잘림
→ 임베딩이 제대로 될 리 없음
→ 뒤에 리랭커를 붙여도 소용없음 (쓰레기 in = 쓰레기 out)

스플리터 발전 순서: 1. 글자수 기반 → 단어 깨짐 2. 공백 기반 → 문장 깨짐 3. 정규식 기반 → 유연성 부족 4. 형태소 분석기 → 문장 정확 인식 5. LLM 토크나이저 → 가장 정확

LLM을 이용한 청크 품질 평가 (3가지 기준)

기준 설명
임베딩 적합성 이 청크를 임베딩했을 때 유사도 검색이 잘 맞을 것인가
시멘틱 독립성 청크가 독립된 의미를 갖고 있는가 (날씨+샐러드 혼재 → NG)
시멘틱 완전성 원문의 정보가 청킹 과정에서 누락되지 않았는가
# LLM을 이용한 청크 품질 평가
chunk_eval_prompt = """원문 페이지와 이로부터 생성된 청크들을 비교하세요.

원문: {original_page}
청크들: {chunks}

평가 기준:
1. 임베딩 적합성: 각 청크를 임베딩하면 유사도 검색이 잘 될까?
2. 시멘틱 독립성: 각 청크가 하나의 독립된 주제를 다루고 있는가?
3. 시멘틱 완전성: 원문 정보가 청킹 과정에서 누락되지 않았는가?

각 기준별 OK/NG와 근거를 반환하세요."""

벡터 검색 튜닝 — LLM으로 테스트셋 자동 생성

# LLM에게 청크 기반 QA 테스트셋 생성 의뢰
# 큰 모델: 청크 많이 + 질문 많이 = 한 번에
# 작은 모델: 청크 3개씩 + 질문 2개씩 = 여러 번 반복
test_gen_prompt = """아래 500개 청크를 보고:
1. 검증용 질문 200개를 만들어주세요
2. 각 질문에 관련된 청크 ID를 매핑해주세요
3. 예상 유사도 점수도 포함해주세요"""

# → 이 테스트셋으로 벡터 DB 검색 결과와 비교
# → 불일치 항목에서 임베딩 모델 교체 여부 판단

튜닝 영향도 vs 부담

튜닝 항목 영향도 부담도 비고
RAG 체인 변경 최대 최대 전체 아키텍처 변경
임베딩 모델 변경 전체 데이터 재임베딩 필요
비임베딩 강화 BM25, 메타데이터 추가
부분 요소 교체 소~중 리랭커 교체 등

⚠️ 최신 업데이트: 2026 벤치마크에 따르면 RecursiveCharacterTextSplitter (400~512 토큰, 10~20% overlap)가 여전히 시작점으로 권장된다. NAACL 2025는 "200-word 고정 청크가 시멘틱 청킹과 동등하거나 우수"하다고 보고했다. 2026의 late chunking, contextual retrieval이 overlap 조정보다 큰 성능 향상을 보이는 새로운 트렌드다.

실무 적용

# 실무 청크 튜닝 파이프라인
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 1단계: 시작점 — 400~512 토큰, 10~20% overlap
splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
    separators=["\n\n", "\n", "。", ".", " "]
)

# 2단계: LLM으로 청크 품질 검증
# 3단계: 스플리터 파라미터 조정 또는 스플리터 교체
# 4단계: 벡터 검색 테스트셋으로 end-to-end 검증

핵심 체크포인트

  • ✅ 대부분 기업이 청크 스플리터에서 실패 — 글자수 기반 스플리팅은 임베딩을 망가뜨림
  • ✅ 청크 품질 검증 3기준: 임베딩 적합성·시멘틱 독립성·시멘틱 완전성 (LLM으로 자동 평가)
  • ✅ 비임베딩 요소 강화(BM25 병행, 메타데이터)가 가장 현실적인 품질 개선 방법

부록 A: 용어 사전

용어 설명
어텐션 편향 (Attention Bias) 입력 토큰의 구성에 따라 어텐션 계산 결과가 달라지는 현상
입력 편향 (Input Bias) 시스템 프롬프트·컨텍스트로 유도하는 어텐션 편향
출력 편향 (Output Bias) LLM이 생성한 토큰이 후속 토큰 생성에 영향을 주는 편향
어텐션 희석 (Attention Dilution) 토큰 수 증가 → 개별 토큰의 어텐션 기여도 감소
크로스 인코더 쿼리+문서 쌍을 BERT에 입력하여 유사도 점수를 출력하도록 학습한 모델/방법
Refine (고유명사) 앞 요약을 바탕으로 뒤 데이터를 합쳐 재요약하는 기법
RAPTOR Recursive Abstractive Processing for Tree-Organized Retrieval
MapReduce 청크별 병렬 요약 → 요약의 요약으로 리듀스
MapRefine 순차적으로 앞 요약+뒷 데이터를 합쳐 재요약 (서사 구조 보존)
BM25 형태소 분석 + TF-IDF 기반 키워드 매칭 알고리즘
Stuff 전체 문서를 한 번에 LLM에 전달하는 요약 방식
CoT (Chain of Thought) 출력 편향을 활용하여 중간 추론을 생성하게 하는 기법
컨텍스트 혼합 RAPTOR에서 시멘틱은 유사하나 컨텍스트가 다른 청크가 함께 클러스터링되는 문제
유사 시멘틱 문장 구조(템플릿)가 동일하여 임베딩이 같게 나오는 문제
LLM-as-Judge LLM을 평가자로 활용하는 방식
RAGAS Retrieval Augmented Generation Assessment 프레임워크

부록 B: 비교표

B-1. 리랭커 방식 비교

항목 크로스 인코더 LLM Pointwise LLM Listwise 2-Stage 하이브리드
호출 횟수 N회 N회 1회 크로스N + LLM 1
속도 5~10ms 200ms×N 200~500ms ~510ms
프롬프트 통제 불가 가능 가능 가능 (2차)
정확도 (상대) 95% 90% 100% (기준) 최고
비용/1K쿼리 ~$0.50 높음 $5~10 ~$6
추천 용도 1차 필터 단건 검증 최종 정렬 프로덕션

B-2. 요약 기법 비교

기법 서사 보존 병렬 처리 정보 손실 적합 문서
Stuff N/A N/A 최소 짧은 문서
MapReduce 낮음 가능 중간 대규모·독립 섹션
MapRefine 높음 불가 낮음 순서 의존 문서
ClusterMapRefine 중간 부분 높음 (클러스터링 실패 시) 주제 단일 문서

B-3. RAG 튜닝 영향도 매트릭스

튜닝 대상 영향도 비용 리스크 권장 순서
청크 스플리터 최고 낮음 중간 1순위
비임베딩 강화 중간 낮음 낮음 2순위
리랭커 교체 중간 중간 낮음 3순위
임베딩 모델 높음 높음 높음 (재인덱싱) 4순위
RAG 체인 최고 최고 최고 최후 수단

부록 C: 추천 참고 자료 & 링크

공식 문서·프레임워크

임베딩 모델

리랭커

논문·연구

청크 전략

난이도
에피소드
질문
카드를 로딩 중...
답변

클릭하거나 Space를 눌러 뒤집기

0 / 0
학습 진도 0%
이동   Space 뒤집기   R 셔플